package com.zhao.interceptor;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;

/**
 * 审计接口，自动注入用户id以及自动获取注入更新时间和创建时间
 */
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class AuditingInterceptor implements Interceptor {
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
		SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
		Object parameter = invocation.getArgs()[1];
		Field[] fields = parameter.getClass().getDeclaredFields();
		Date currentDate = new Date();
		if (SqlCommandType.UPDATE == sqlCommandType) {
			for (Field field : fields) {
				if (AnnotationUtils.getAnnotation(field, LastModifiedBy.class) != null) {
					field.setAccessible(true);
					field.set(parameter, 1);
					field.setAccessible(false);
				}
				if (AnnotationUtils.getAnnotation(field, LastModifiedDate.class) != null) {
					field.setAccessible(true);
					field.set(parameter, currentDate);
					field.setAccessible(false);
				}
			}
		} else if (SqlCommandType.INSERT == sqlCommandType) {
			for (Field field : fields) {
				if (AnnotationUtils.getAnnotation(field, CreatedBy.class) != null) {
					field.setAccessible(true);
					field.set(parameter, 2);
					field.setAccessible(false);
				}
				if (AnnotationUtils.getAnnotation(field, CreatedDate.class) != null) {
					field.setAccessible(true);
					field.set(parameter, currentDate);
					field.setAccessible(false);
				}
			}
		}
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		if (target instanceof Executor) {
			return Plugin.wrap(target, this);
		} else {
			return target;
		}
	}

	@Override
	public void setProperties(Properties properties) {

	}
}